import math
import hashlib
import logging
from sqlalchemy.orm import Session
from app.database.models import File
from typing import List, Optional, Set
import threading

# 配置日志记录器
logger = logging.getLogger(__name__)

class BloomFilter:
    """布隆过滤器实现，用于快速判断文件哈希是否已存在"""
    
    def __init__(self, capacity: int = 1000000, error_rate: float = 0.001):
        """初始化布隆过滤器
        
        Args:
            capacity: 预期元素数量
            error_rate: 允许的错误率
        """
        self.capacity = capacity
        self.error_rate = error_rate
        self.bit_size = self._get_bit_size(capacity, error_rate)
        self.hash_count = self._get_hash_count(self.bit_size, capacity)
        self.bit_array = [False] * self.bit_size
        self._cache = set()  # 用于缓存已知元素
        self._lock = threading.RLock()  # 用于线程安全操作
        
        logger.info(f"初始化布隆过滤器: 容量={capacity}, 错误率={error_rate}, 位数组大小={self.bit_size}, 哈希函数数量={self.hash_count}")
    
    def _get_bit_size(self, capacity: int, error_rate: float) -> int:
        """计算最佳位数组大小"""
        return int(-capacity * math.log(error_rate) / (math.log(2) ** 2)) + 1
    
    def _get_hash_count(self, bit_size: int, capacity: int) -> int:
        """计算最佳哈希函数数量"""
        return int(bit_size / capacity * math.log(2)) + 1
    
    def _get_hash_values(self, item: str) -> List[int]:
        """获取元素的多个哈希值"""
        hash_values = []
        for i in range(self.hash_count):
            # 使用不同的种子生成多个哈希值
            hash_obj = hashlib.md5(f"{item}:{i}".encode())
            hash_value = int(hash_obj.hexdigest(), 16) % self.bit_size
            hash_values.append(hash_value)
        return hash_values
    
    def add(self, item: str) -> None:
        """添加元素到布隆过滤器"""
        with self._lock:
            # 向缓存中添加元素
            self._cache.add(item)
            # 设置对应位置的标志位
            for hash_value in self._get_hash_values(item):
                self.bit_array[hash_value] = True
    
    def contains(self, item: str) -> bool:
        """检查元素是否可能存在于布隆过滤器中"""
        if not item:
            logger.warning("尝试检查空哈希值")
            return False
            
        # 先检查缓存
        if item in self._cache:
            return True
        
        # 如果所有哈希值对应的位都为True，则可能存在
        hash_values = self._get_hash_values(item)
        for i, hash_value in enumerate(hash_values):
            if not self.bit_array[hash_value]:
                return False  # 如果有任意一位不为True，则肯定不存在
        
        return True  # 可能存在（有一定错误率）
    
    def batch_add(self, items: List[str]) -> None:
        """批量添加元素"""
        for item in items:
            self.add(item)
    
    def clear(self) -> None:
        """清空布隆过滤器"""
        with self._lock:
            self.bit_array = [False] * self.bit_size
            self._cache.clear()
    
    def load_from_database(self, db: Session) -> None:
        """从数据库加载文件哈希值"""
        with self._lock:
            # 清空当前内容
            self.clear()
            
            # 查询所有文件哈希值
            hashes = db.query(File.hash).distinct().all()
            hash_values = [h[0] for h in hashes if h[0]]
            
            # 批量添加到布隆过滤器
            self.batch_add(hash_values)
            
            logger.info(f"从数据库加载了 {len(hash_values)} 个哈希值到布隆过滤器")

# 创建全局单例
file_hash_filter = BloomFilter(capacity=1000000, error_rate=0.001) 